package com.yuliang.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuliang.constants.SystemConstants;
import com.yuliang.domain.R;
import com.yuliang.domain.dto.ArticleDto;
import com.yuliang.domain.entity.Article;
import com.yuliang.domain.entity.ArticleTag;
import com.yuliang.domain.entity.Category;
import com.yuliang.domain.vo.*;
import com.yuliang.exception.SystemException;
import com.yuliang.mapper.ArticleMapper;
import com.yuliang.service.ArticleService;
import com.yuliang.service.ArticleTagService;
import com.yuliang.service.CategoryService;
import com.yuliang.service.TagService;
import com.yuliang.utils.BeanCopyUtils;
import com.yuliang.utils.RedisCache;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 文章表(Article)表服务实现类
 *
 * @author makejava
 * @since 2023-09-18 21:02:27
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private CategoryService categoryService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ArticleTagService articleTagService;


    @Override
    public R hotArticleList() {
        //构造查询条件
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);//正常发布
        queryWrapper.orderByDesc(Article::getViewCount);//根据浏览量降序排列
        IPage<Article> page = new Page<>(1,10);
        page(page,queryWrapper);
        //vo
        List<Article> articles = page.getRecords();
        List<HotArticleVo> list = new ArrayList<>();
        for (Article article:articles) {
            HotArticleVo hotArticleVo = new HotArticleVo();
            BeanUtils.copyProperties(article,hotArticleVo);
            list.add(hotArticleVo);
        }
        return R.okResult(list);
    }

    @Override
    public R articleList(Integer pageNum, Integer pageSize, Long categoryId) {
        //状态正常，浏览量降序，根据categoryId查询
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getStatus,SystemConstants.ARTICLE_STATUS_NORMAL);
        queryWrapper.eq(Objects.nonNull(categoryId) && categoryId > 0,Article::getCategoryId,categoryId);
        queryWrapper.orderByDesc(Article::getViewCount);

        IPage<Article> page = new Page<>(pageNum,pageSize);
        page(page,queryWrapper);
        List<Article> records = page.getRecords();
        for (Article article:records) {//封装categoryName
            article.setCategoryName(categoryService.getById(article.getCategoryId()).getName());
        }
        List<ArticleListVo> articleListVos = BeanCopyUtils.copyBeanList(records, ArticleListVo.class);//vo
        return R.okResult(new PageVo(articleListVos,page.getTotal()));
    }

    @Override
    public R getArticleDetail(Long id) {
        Article article = getById(id);
        //从redis获取浏览量
        Integer viewCount = redisCache.getCacheMapValue("article:viewCount", id.toString());
        article.setViewCount(viewCount.longValue());
        //分类名
        Category category = categoryService.getById(article.getCategoryId());
        article.setCategoryName(category.getName());

        ArticleDetailVo articleDetailVo = BeanCopyUtils.copyBean(article, ArticleDetailVo.class);
        return R.okResult(articleDetailVo);
    }

    @Override
    public R updateViewCount(Long id) {
        //更新redis中对应 id的浏览量
        redisCache.incrementCacheMapValue("article:viewCount",id.toString(), 1);
        return R.okResult();
    }

    @Override
    public R writeArticle(ArticleDto articleDto) {
        //新增文章
        Article article = BeanCopyUtils.copyBean(articleDto, Article.class);
        save(article);
        //添加 博客和标签的关联
        List<Long> tags = articleDto.getTags();
        List<ArticleTag> list = new ArrayList<>();
        for (Long tagId:tags) {
            list.add(new ArticleTag(article.getId(),tagId));
        }
        articleTagService.saveBatch(list);
        return R.okResult();
    }

    @Override
    public R getPageList(Integer pageNum, Integer pageSize, String title, String summary) {
        IPage<Article> page = new Page<>(pageNum,pageSize);//根据 标题和摘要 模糊查询
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasLength(title), Article::getTitle,title);
        queryWrapper.like(StringUtils.hasLength(summary), Article::getSummary,summary);
        page(page,queryWrapper);

        List<ArticlePageVo> articlePageVos = BeanCopyUtils.copyBeanList(page.getRecords(), ArticlePageVo.class);

        return R.okResult(new PageVo(articlePageVos,page.getTotal()));
    }

    @Override
    public R getArticleContentDetail(Long id) {
        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Article::getId,id);
        Article article = getOne(queryWrapper);
        //获取标签
        ArticleContentDetailVo articleContentDetailVo = BeanCopyUtils.copyBean(article, ArticleContentDetailVo.class);
        List<Long> tags = articleTagService.getTagsByArticleId(article.getId());
        articleContentDetailVo.setTags(tags);
        return R.okResult(articleContentDetailVo);
    }

    @Override
    public R updateArticle(ArticleContentDetailVo articleVo) {
        Article article = BeanCopyUtils.copyBean(articleVo, Article.class);
        updateById(article);
        //更新标签
        LambdaQueryWrapper<ArticleTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ArticleTag::getArticleId,article.getId());
        articleTagService.remove(queryWrapper);

        List<ArticleTag> list = new ArrayList<>();
        for (Long tagId:articleVo.getTags()) {
            list.add(new ArticleTag(article.getId(),tagId));
        }
        articleTagService.saveBatch(list);
        return R.okResult();
    }

    @Override
    public R deleteById(Long id) {
        removeById(id);
        //删除标签
        LambdaQueryWrapper<ArticleTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ArticleTag::getArticleId,id);
        articleTagService.remove(queryWrapper);
        return R.okResult();
    }
}
